const { getReadableFromUTCToLocal } = require("../../../utils/datetime");

function buildDataTableSystemPrompt({ userName, timezoneOffsetInSeconds }) {
    return `
    You are a freelancer agent. You take up user's tasks, perform them and report back to user in Google sheets type format.
    `;
}

function buildDataTableSchemaPrompt({
    task,
    userName,
    timezoneOffsetInSeconds,
}) {
    return `
    === TASK OF USER ===
    ${task}

    === USER DATA ===
    User's name: ${userName}
    User's timezone offset: ${timezoneOffsetInSeconds}

    === UNIVERSE DATA ===
    Current date and time: ${getReadableFromUTCToLocal(
        new Date(),
        timezoneOffsetInSeconds
    )}

    === YOUR TASK ===
    Given this task, if we have to inform user after performing this task, what should the columns be and for each column what should the data be?

    RULES:
    1. Keep it lightweight. Don't include columns that the user didn't mention. 
    2. If the user wanted some specific information covered, they would have mentioned it.

    === OUTPUT FORMAT JSON ===
    {
        "columns": [
            {
                "key": "column1", // unique no spaces lowercased (_ is fine) key for the column
                "name": "Column 1", // readable name of the column
                "type": "string", // type of the column
                "description": "description1" // description of the column
            },
            {
                "key": "column2",
                "name": "Column 2",
                "type": "string",
                "description": "description2"
            }
        ]
    }

    RETURN ONLY THE JSON OBJECT AND NOTHING ELSE.
    `;
}

function buildDataTableOpsPrompt({
    task,
    userName,
    timezoneOffsetInSeconds,
    dtSchema,
    logs,
    triggerInput,
    availableAgentsString,
    parentNodeStructuredOutput,
}) {
    return `
=== USER DATA ===
User's name: ${userName}
User's timezone offset: ${timezoneOffsetInSeconds}

=== UNIVERSE DATA ===
Current date and time: ${getReadableFromUTCToLocal(
        new Date(),
        timezoneOffsetInSeconds
    )}

===CONTEXT====

User wants to perform the following task:
${task}
${triggerInput ? `Trigger input: ${triggerInput}` : ""}

We maintain a data table while performing this task on behalf of user.

===DATA TABLE SCHEMA===
${JSON.stringify(dtSchema, null, 2)}

The data table is maintained in MongoDB

===YOUR TASK===
Start by checking if you have enough information to add or update rows in the data table.

+ **Decomposition Strategy:** If the user's task requires finding multiple distinct items (e.g., multiple products, companies, people) AND details about each item:
+   1. **Prioritize Identification:** First, determine if you know the specific items (e.g., the names of the 3 providers). If not, your primary goal is to *identify* these items.
+   2. **Use 'work_on_subtask_before_deciding':** Create a subtask specifically focused on *finding the list* of these core items (e.g., "Find the names of three SaaS providers for logical reasoning tests").
+   3. **Use 'decided_to_add_or_update_rows':** Once you have the list of items from the previous step, use this action to create a row for *each* identified item. Populate the key identifier (e.g., 'saas_provider' name) and create specific subtasks for each row to gather the remaining details (e.g., "Find pricing and features for provider X").

If you do NOT yet have the data required to fill in the rows even partially (especially the key identifying information for multiple distinct items), do not create placeholder rows. Instead, identify and execute the subtasks that will help you discover the key partial data first using one of the available agents, following the Decomposition Strategy above.

Once you have some critical information (like the names/identifiers of the items) to create subtasks to add/update rows, you can then proceed to create rows or update existing ones.

===AVAILABLE AGENTS===
${availableAgentsString}

===HERE'S WHAT WE WE LEARNT FROM THE MOST RECENT AGENT===
${
    parentNodeStructuredOutput
        ? JSON.stringify(parentNodeStructuredOutput, null, 2)
        : "No parent node structured output found"
}

===PREVIOUS ATTEMPTS===
${logs
    .map(
        (log) => `${log.type}
${log.message}`
    )
    .join("\n")}

===YOUR ACTIONS===
1. actionCode = "decided_to_add_or_update_rows"
- data = {
    "rows": [
        {
            "rowId": <number>, // if you are updating an existing row, you need to include the rowId here. if you are adding a new row, you need to leave it empty.
            "<key>": "<value or placeholder or empty>",
            "<key>": "<value or placeholder or empty>" // in line with the data table schema (rowId is automatically generated by the system. Each key here MUST be present in the data table schema)
            ...
            "subTask": <string that works on this row. string. optional. if the row has all the data to achieve user task and no further work is required, you can leave it empty. note this particular key won't be part of the schema> // each sub task here will work only on the respective row of the data table. 
            // ADD SUB TASK ONLY AND ONLY IF YOU DO NOT HAVE ENOUGH INFORMATION TO UPDATE THE ROW AND MORE WORK IS NEEDED.
            // WHEN TO ADD SUB TASK:
            // 1. If you do not have enough information to update the row and more work is needed. i.e ANY VALUE OF A KEY IN THE ROW IS MISSING. 
            // WHEN TO NOT ADD SUB TASK:
            // 1. If you already have all the information. THEN DON'T ADD A SUB TASK JUST TO VERIFY THE INFORMATION.
        }
    ],
}
IMPORTANT: THERE MUST BE SAME NUMBER OF ROWS IN THE DATA TABLE AS THE NUMBER OF SUB TASKS.
When to pick this action?
- When you think completing this task will require adding new rows to the data table and you have enough information to add new rows and it's subtasks can be worked on in silos without colliding with each other and accurately. And there's no benefit in first creating a subtask to find some information and then adding/updating rows.
- When you have information to add new rows to the data table
- What are subtasks for each row
-- each sub task here will work only on the respective row of the data table.
-- you need to break down the task into sub tasks based on the data table schema while making sure that each sub task works only on the respective row of the data table. Also keep enough information in the subtask so that it can work on that task.
REGARDING NUMBER OF ROWS:
- Analyze user's task in detail to understand how many rows are needed. Unless user specificies clearly (like they want 'all' or 'x of them' or equivalent), you can assume the user wants 'a' one row detail.
- If the user wants many rows of data, they would have mentioned it in the task description. When in doubt, assume user wants one row (i.e err on the lesser data always)
VAGUE ENTRIES VS PRECISE ENTRIES:
- Unless the user specifically states that they want exact precise information or provides certain format for the columns. Even if you have generic information, you can assume user's task is complete.
- Don't over work to find precise information. If user's task is to find a list of items, don't try to find precise information for each item. UNLESS USER EXPLICITLY SPECIFIES OTHERWISE.


2. actionCode = "need_more_info_from_data_table"
- data = {
    "filters": {} // any filters to narrow down the rows to update (flowId and accountId are automatically added. You don't need to include them. Any other filters that are mongodb compatible that will go into mongodb find query)
    "pageSize": 10, // how many rows do you need to know? // keep this 10 or lesser
    "page": 1 // which page do you need to know?
}
When to pick this action?
- When you don't have enough information to decide what to do with the data table
- When you think you need more information to decide what to do with the data table

3. actionCode = "work_on_subtask_before_deciding"
- data = {
    "subTask": "<string>", // the sub task you want to work on first. **Focus:** Use this primarily when you need to identify a list of key items/entities (e.g., names, IDs) before you can create rows for detailed data gathering on each.
    "agentCode": "<string>", // the agent code you want to pass the work to
    "aiData": {
        <keys here are the keys of the agent input. values are the values to be passed to the agent for that key.> 
        <for the task key, make sure the input is structured and includes ALL possible information that the agent would require. For ex: assume the agent does not have access to original task. Your input is THE ONLY information the agent would act upon. (IMPORTANT)>
        // Note that the keys here are directly the nodes inside input.parameters. Don't start with parameters again.
    },
}


===HOW ARE SUBTASKS HANDLED?===
Each sub task is handled by a particular agent. That agent will be given the sub task you decide + the associated row document you decided. 
The agent will then work on the sub task and return with the result required to update the row (if any BUT IT WONT UPDATE THE ROW BY ITSELF)
When the agent is done, we update the row with the result and the node status is set to "completed". The agent doesn't know how the row is updated. 
It just is responsible for using it's own actions and to return with information as per the sub task.
It uses the information available in the row document as context along with the sub task to come up with the result.

===DECISION MAKING STRATEGY===
Example 1: If user asked to find three authors and research on them but they didn't mention who the authors are.
+ **Step 1: Identify Authors:** Realize you don't know the authors yet. Use actionCode: "work_on_subtask_before_deciding" with a subTask like "Find three author names according to user's filters". Avoid asking for research details in this initial subtask.
+ **Step 2: Research Each Author:** Once the first subtask returns the names (e.g., JK Rowling, Dan Brown, JRR Tolkien), use actionCode: "decided_to_add_or_update_rows". Create three separate rows:
+   - Row 1: {"author_name": "JK Rowling", "subTask": "Research JK Rowling's biography and works"}
+   - Row 2: {"author_name": "Dan Brown", "subTask": "Research Dan Brown's biography and works"}
+   - Row 3: {"author_name": "JRR Tolkien", "subTask": "Research JRR Tolkien's biography and works"}
+ This ensures that the identification happens first, and then the detailed research for each author is handled in parallel, distinct subtasks, preventing overlap or redundant work.

- It's better first to find the authors before deciding to add rows since once you decide to add rows and create placeholders, then the three new tasks will work in silos and might come up with same others.
- Instead if you first create a subtask to find three author names according to user's filters. then for each author name, you can create the rows with author name and subtask. then each subtask works in its own silo and comes up with unique results. they wont collide since they are working on different author names.

===BE VERY CAREFUL ABOUT THE SUB TASKS YOU CREATE===
- User might not want all the information we want to provide. Deeply analyze their query. Only create sub tasks that are necessary to fulfill user's details. 
- If user wants specific information clearly wanted (for which you want to produce a new sub task), user will specify it. 
- Unless user specifies in the task description, they want a particular column for that row, don't create a subtask to find that column.

===OUTPUT FORMAT JSON===
{
    "thinking": "<string>", // your thinking and reasoning to come up with the action code and data. This thinking is shown to the user. So you can address the user as 'you' in this field.
    "actionCode": "<string>", // one of the action codes above
    "data": {} // data for the action code
}

RETURN ONLY THE JSON OBJECT AND NOTHING ELSE.
`;
}

function buildDataTableDocUpdatePrompt({
    task,
    userName,
    timezoneOffsetInSeconds,
    shortlistedDocuments,
    learnedRows,
    dtSchema,
}) {
    return `
=== TASK OF USER ===
${task}

=== YOUR TASK ===
Given user's task and learnings from the latest work, you need to update the documents (if any)
The documents are saved in MongoDB and reach document has a rowId. 
You need to make sure only the updated documents are returned with rowId and updated fields.

=== LEARNINGS FROM THE LATEST WORK ===
${JSON.stringify(learnedRows, null, 2)}

=== USER DATA ===
User's name: ${userName}
User's timezone offset: ${timezoneOffsetInSeconds}

=== UNIVERSE DATA ===
Current date and time: ${getReadableFromUTCToLocal(
    new Date(),
    timezoneOffsetInSeconds
)}

=== DATA TABLE SCHEMA ===
${JSON.stringify(dtSchema, null, 2)}

=== DOCUMENTS ===
${shortlistedDocuments.map((x) => JSON.stringify(x, null, 2)).join("\n\n")}

=== OUTPUT FORMAT JSON ===
{
    "thinking": "<string>", // your thinking and reasoning to come up with the updates you have made. short and concise.
    "updates": [
        {
            "rowId": <number>, // rowId of the document to update
            ... // any other fields to update. keys are found in the document itself or in the data table schema. The value should be updated based on the learnings from the latest work and make sure you stick to the data table schema for value type.
        }
    ],
    "updateSummary": "<string>", // a readable summary of the updates you have made so that user can understand what you have done easily.
}

RETURN ONLY THE JSON OBJECT AND NOTHING ELSE.
    `;
}

module.exports = {
    buildDataTableSchemaPrompt,
    buildDataTableSystemPrompt,
    buildDataTableOpsPrompt,
    buildDataTableDocUpdatePrompt,
};
